package org.dfl.taverna;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.dfl.data.ConfigDirectory;
import org.dfl.log.Logger;
import org.dfl.plugin.DflPlugin;

import net.sf.taverna.raven.repository.Artifact;
import net.sf.taverna.raven.repository.ArtifactNotFoundException;
import net.sf.taverna.raven.repository.ArtifactStateException;
import net.sf.taverna.raven.repository.ArtifactStatus;
import net.sf.taverna.raven.repository.DownloadStatus;
import net.sf.taverna.raven.repository.Repository;
import net.sf.taverna.raven.repository.RepositoryListener;

/**
 *
 * @author Lukas
 */
public class WrapperRepository implements Repository {
    
    private static final String PROFILE = "wrapper-profile-1.7.1.0.xml";
    private static final String RAVEN_PROFILE_PROP = "raven.profile";
    private static final String RAVEN_ECLIPSE_PROP = "raven.eclipse";

    private Artifact artifactSingleton;
    private WrapperDownloadStatus downloadStatus;
    private Set<RepositoryListener> listeners;
    private ArtifactStatus status;
    
    private InputStream getResource(String name) throws IOException {
    	URL url = DflPlugin.getURLFromPlugin(name);
    	return url.openStream();
    }

    public WrapperRepository() {
        downloadStatus = new WrapperDownloadStatus();
        listeners = new HashSet<RepositoryListener>();
        
        ConfigDirectory conf = ConfigDirectory.getInstance();
        
        if (conf.getStoredFile(PROFILE) == null) {
            try {
                conf.storeFile(PROFILE, getResource("conf/" + PROFILE));
            } catch (IOException ex) {
                Logger.logException(ex);
            }
        }
        
        artifactSingleton = null;
        status = ArtifactStatus.Unknown;
        
        System.setProperty(RAVEN_PROFILE_PROP,
                conf.getStoredFile(PROFILE).toURI().toString());
        
        if (System.getProperty(RAVEN_ECLIPSE_PROP) == null)
            System.setProperty(RAVEN_ECLIPSE_PROP, "");
    }

    public void addArtifact(Artifact artifact) {
        artifactSingleton = artifact;
    }

    public void addRemoteRepository(URL url) {
    }

    public ClassLoader getLoader(Artifact artifact, ClassLoader loader) {
    	return getClass().getClassLoader();
    }

    public ArtifactStatus getStatus(Artifact artifact) {
        return status;
    }

    public DownloadStatus getDownloadStatus(Artifact artifact) throws ArtifactStateException, ArtifactNotFoundException {
        return downloadStatus;
    }

    public List<Artifact> getArtifacts() {
        List<Artifact> list = new ArrayList<Artifact>();
        
        if (artifactSingleton != null)
            list.add(artifactSingleton);
        
        return list;
    }

    public List<Artifact> getArtifacts(ArtifactStatus status) {
        List<Artifact> list = new ArrayList<Artifact>();
        
        if (status == this.status && artifactSingleton != null)
            list.add(artifactSingleton);
        
        return list;
    }

    public void update() {
        changeStatus(ArtifactStatus.Queued);
        changeStatus(ArtifactStatus.PomFetching);
        changeStatus(ArtifactStatus.Pom);
        changeStatus(ArtifactStatus.Analyzed);
        changeStatus(ArtifactStatus.JarFetching);
        changeStatus(ArtifactStatus.Jar);
        changeStatus(ArtifactStatus.Ready);
    }
    
    private void changeStatus(ArtifactStatus newStatus) {
        for (RepositoryListener listener : listeners) {
            listener.statusChanged(artifactSingleton, status, newStatus);
        }
        
        status = newStatus;
    }

    public void addRepositoryListener(RepositoryListener listener) {
        listeners.add(listener);
    }

    public void removeRepositoryListener(RepositoryListener listener) {
        listeners.remove(listener);
    }

    public Artifact artifactForClass(Class aClass) throws ArtifactNotFoundException {
        return artifactSingleton;
    }

    private class WrapperDownloadStatus implements DownloadStatus {

        public int getTotalBytes() {
            return 0;
        }

        public int getReadBytes() {
            return 0;
        }

        public boolean isFinished() {
            return true;
        }
    }
}
